package com.galen.wxRead.server;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.galen.wxRead.bean.RetBaseVo;
import com.galen.wxRead.bean.wxBean.WxBaseBean;
import com.galen.wxRead.bean.wxBean.WxGetA8KeyBean;
import com.galen.wxRead.bean.wxBean.WxHeartBean;
import com.galen.wxRead.bean.wxBean.WxReadBean;
import com.galen.wxRead.bean.wxTo.WxBaseTo;
import com.galen.wxRead.bean.wxTo.WxGetA8KeyTo;
import com.galen.wxRead.bean.wxTo.WxReadBizArticleTo;
import com.galen.wxRead.config.ServerConfig;
import com.galen.wxRead.core.pojo.BizException;
import com.galen.wxRead.core.pojo.R;
import com.galen.wxRead.domain.ReadInfo;
import com.galen.wxRead.domain.ReadInit;
import com.galen.wxRead.domain.ReadUser;
import com.galen.wxRead.domain.ReadWx;
import com.galen.wxRead.mapper.ReadInfoMapper;
import com.galen.wxRead.mapper.ReadUserMapper;
import com.galen.wxRead.mapper.ReadWxMapper;
import com.galen.wxRead.redis.RedisCache;
import com.galen.wxRead.redis.RedisKeys;
import com.galen.wxRead.utils.OkHttpUtils;
import com.galen.wxRead.utils.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.apache.tomcat.util.threads.ThreadPoolExecutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

@Service
public class OpenApiServer {

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ReadWxMapper readWxMapper;

    @Autowired
    private ReadInfoMapper readInfoMapper;

    @Autowired
    private ReadUserMapper readUserMapper;

    @Autowired
    private WxApiServer wxApiServer;

    @Autowired
    private ServerConfig serverConfig;

    private static ExecutorService executorService;

    static {
        executorService = new ThreadPoolExecutor(200, 500, 60L, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5000), new ThreadPoolExecutor.CallerRunsPolicy());
    }

    static ExecutorService fixedThreadPool = Executors.newFixedThreadPool(100);


    public static SimpleDateFormat formater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    ////////////接口类////////////////////////////////////

    /**
     * 获取阅读数
     *
     * @return
     */
    public RetBaseVo getReadWx() {
        RetBaseVo retBaseVo = new RetBaseVo();
        ReadWx readWx = new ReadWx();
        readWx.setReadStatus(0);
        readWx.setType(2);
        int typeOneNum = readWxMapper.count(readWx);
        readWx.setType(1);
        int typeTwoNum = readWxMapper.count(readWx);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("two", typeOneNum);
        jsonObject.put("first", typeTwoNum);
        jsonObject.put("all", typeTwoNum + typeOneNum);
        retBaseVo.setMsg("获取成功");
        retBaseVo.setCode(200);
        retBaseVo.setData(jsonObject);
        return retBaseVo;
    }

    /**
     * 根据id获取订单
     *
     * @param taskId
     * @return
     */
    public RetBaseVo getOrder(long taskId) {
        ReadInfo readInfo = readInfoMapper.selectReadInfoById(taskId);
        RetBaseVo retBaseVo = new RetBaseVo();
        if (readInfo != null) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("task_id", readInfo.getId());
            jsonObject.put("url", readInfo.getUrl());
            jsonObject.put("end_at", readInfo.getComTime());
            jsonObject.put("status", readInfo.getState());
            jsonObject.put("start_read_num", readInfo.getStartTime());
            jsonObject.put("init_read_num", readInfo.getInitNum());
            jsonObject.put("end_read_num", readInfo.getEndNum());
            jsonObject.put("current_num", readInfo.getReadNum());
            retBaseVo.setCode(200);
            retBaseVo.setMsg("success");
            retBaseVo.setData(jsonObject);
        } else {
            retBaseVo.setCode(400);
            retBaseVo.setMsg("任务不存在");
        }
        return retBaseVo;
    }

    /**
     * 删除订单
     *
     * @param taskId
     * @return
     */
    public RetBaseVo delOrder(long taskId) {
        RetBaseVo retBaseVo = new RetBaseVo();
        ReadInfo readInfo = readInfoMapper.selectReadInfoById(taskId);
        if (readInfo != null) {
            //删除订单
            redisCache.deleteObject(RedisKeys.orderStatus(readInfo.getUrl()));
            readInfoMapper.deleteById(taskId);
            retBaseVo.setCode(200);
            retBaseVo.setMsg("订单已删除");
        } else {
            retBaseVo.setCode(400);
            retBaseVo.setMsg("订单不存在");
        }
        return retBaseVo;
    }

    /**
     * 批量删除已完成订单
     *
     * @return
     */
    public RetBaseVo bitchDelOrder() {
        RetBaseVo retBaseVo = new RetBaseVo();
        List<ReadInfo> readInfoList = new ArrayList<>();
        ReadInfo readSearchInfo = new ReadInfo();
        readSearchInfo.setState(2);
        readInfoList = readInfoMapper.selectReadInfoList(readSearchInfo);
        for (ReadInfo readInfo : readInfoList) {
            redisCache.deleteObject(RedisKeys.orderStatus(readInfo.getUrl()));
        }
        readInfoMapper.deleteAll();
        retBaseVo.setCode(200);
        retBaseVo.setMsg("订单已删除");
        return retBaseVo;
    }

    /**
     * 获取订单列表
     *
     * @param readSearchInfo
     * @return
     */
    public RetBaseVo getOrderList(ReadInfo readSearchInfo) {
        RetBaseVo retBaseVo = new RetBaseVo();
        if (StringUtils.isNotBlank(readSearchInfo.getUrl()) && isNumeric(readSearchInfo.getUrl())) {
            readSearchInfo.setId(Long.parseLong(readSearchInfo.getUrl()));
            readSearchInfo.setUrl("");
        }
        List<ReadInfo> readInfoList = readInfoMapper.selectReadInfoList(readSearchInfo);
        retBaseVo.setCode(200);
        retBaseVo.setMsg("获取成功");
        retBaseVo.setData(readInfoList);
        return retBaseVo;
    }

    /**
     * 批量添加订单
     *
     * @param readInfoList
     * @return
     */
    public RetBaseVo addOrderList(List<JSONObject> readInfoList) {
        RetBaseVo retBaseVo = new RetBaseVo();
        retBaseVo.setMsg("添加完成");
        retBaseVo.setCode(200);
        for (JSONObject jsonObject : readInfoList) {
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    String url = jsonObject.getString("url");
                    int taskNum = jsonObject.getInteger("taskNum");
                    int initNum = jsonObject.getInteger("initNum");
                    addReadTask(url, taskNum, initNum);
                }
            });
        }
        return retBaseVo;
    }

    /**
     * 手动添加初始值并添加到数据库
     *
     * @param url
     * @param taskNum
     * @param initNum
     * @return
     */
    public RetBaseVo addReadTask(String url, int taskNum, int initNum) {
        RetBaseVo retBaseVo = new RetBaseVo();
        //检测是否重复
        boolean add = checkUrl(url);
        if(add) {
            ReadInfo addInfo = readInfoMapper.selectReadInfoByUrl(url);
            if (addInfo == null) {
                redisCache.setCacheObject(RedisKeys.orderStatus(url), 1);
                //保存到数据库
                ReadInfo readInfo = new ReadInfo();
                readInfo.setStartTime(new Date());
                readInfo.setUrl(url);
                readInfo.setNeedNum(taskNum);
                readInfo.setTaskNum(taskNum);
                readInfoMapper.insertReadInfo(readInfo);
                retBaseVo.setCode(0);
                retBaseVo.setMsg("success");
                readInfo = readInfoMapper.selectReadInfoByUrl(url);
                JSONObject dataObj = new JSONObject();
                dataObj.put("task_id", readInfo.getId());
                retBaseVo.setData(dataObj);
                retBaseVo.setCode(200);
                retBaseVo.setMsg("添加成功");
                ReadInfo finalReadInfo = readInfo;
            } else {
                retBaseVo.setCode(400);
                retBaseVo.setMsg("链接重复");
            }
        }else{
            retBaseVo.setCode(400);
            retBaseVo.setMsg("链接不正确");
        }
        return retBaseVo;
    }

    /**
     * 重置任务
     *
     * @return
     */
    public RetBaseVo updateReadTask(long id, int taskNum, int initNum) {
        RetBaseVo retBaseVo = new RetBaseVo();
        ReadInfo addInfo = readInfoMapper.selectReadInfoById(id);
        if (addInfo != null) {
            //检测是否重复
            if (addInfo != null) {
                ReadInfo readInfo = new ReadInfo();
                //保存到数据库
                readInfo.setStartTime(new Date());
                readInfo.setReadNum(0);
                readInfo.setState(0);
                readInfo.setEndNum(0);
                readInfo.setUrl(addInfo.getUrl());
                readInfo.setTaskNum(taskNum);
                readInfoMapper.updateReadInfoByUrl(readInfo);
                //添加链接状态缓存
                redisCache.setCacheObject(RedisKeys.orderStatus(readInfo.getUrl()), 1);
                retBaseVo.setCode(200);
                retBaseVo.setMsg("success");
                readInfo = readInfoMapper.selectReadInfoByUrl(addInfo.getUrl());
                JSONObject dataObj = new JSONObject();
                dataObj.put("task_id", readInfo.getId());
                dataObj.put("init_read_num", readInfo.getInitNum());
                dataObj.put("article_title", "");
                retBaseVo.setData(dataObj);
            } else {
                retBaseVo.setCode(400);
                retBaseVo.setMsg("链接不存在");
            }
        } else {
            retBaseVo.setCode(400);
            retBaseVo.setMsg("链接不存在");
        }
        return retBaseVo;
    }

    //设置阅读用微信状态
    public RetBaseVo setReadWxStatus(int type) {
        RetBaseVo retBaseVo = new RetBaseVo();
        retBaseVo.setCode(200);
        retBaseVo.setMsg("阅读微信状态设置成功");
        redisCache.setCacheObject("readWxStatus", type);
        return retBaseVo;
    }

    public int getReadWxStatus() {
        Object readWxStatusObj = redisCache.getCacheObject("readWxStatus");
        if (readWxStatusObj == null) {
            redisCache.setCacheObject("readWxStatus", 2);
            return 2;
        } else {
            return Integer.parseInt(readWxStatusObj.toString());
        }
    }

    public RetBaseVo setReadWxLimit(int num) {
        RetBaseVo retBaseVo = new RetBaseVo();
        retBaseVo.setCode(200);
        retBaseVo.setMsg("阅读微信并发量设置成功");
        redisCache.setCacheObject("readWxLimit", num);
        return retBaseVo;
    }

    public int getReadWxLimit() {
        Object readWxStatusObj = redisCache.getCacheObject("readWxLimit");
        if (readWxStatusObj == null) {
            redisCache.setCacheObject("readWxLimit", 10);
            return 10;
        } else {
            return Integer.parseInt(readWxStatusObj.toString());
        }
    }
    //////////////任务类//////////////////////////////

    public void readWxTask() {
        while (true) {
            int limit = 10;
            Object readWxLimitObj = redisCache.getCacheObject("readWxLimit");
            if (readWxLimitObj == null) {
                redisCache.setCacheObject("readWxLimit", 10);
            } else {
                limit = Integer.parseInt(readWxLimitObj.toString());
            }
            //查询出指定条数的链接
            ReadInfo readSearchInfo = new ReadInfo();
            readSearchInfo.setState(0);
            readSearchInfo.setLimit(limit);
            List<ReadInfo> readInfoList = readInfoMapper.selectReadInfoLimit(readSearchInfo);
            System.out.println(formater.format(new Date()) + ":发现新的链接:" + readInfoList.size());
            for (ReadInfo readInfo : readInfoList) {
                //获取初始值
                int initNum = readInfo.getInitNum();
                ReadInit readInit = getReadNum(readInfo.getUrl());
                if (readInit.isReadStatus()) {
                    //如果有初始值的,直接进行阅读，没有的获取初始值
                    if (initNum == 0) {
                        //获取当前值,更新信息
                        initNum = readInit.getInitNum();
                        int endNum = initNum + readInfo.getTaskNum();
                        readInfo.setInitNum(initNum);
                        readInfo.setEndNum(endNum);
                        readInfo.setNowNum(initNum);
                        readInfo.setReadNum(0);
                        readInfo.setNeedNum(readInfo.getTaskNum());
                        readInfo.setState(1);
                    }
                    //处理的是未完成的
                    else {
                        //重新获取当前值,计算需要阅读量
                        initNum = readInit.getInitNum();
                        readInfo.setNowNum(initNum);
                        readInfo.setNeedNum(readInfo.getEndNum() - initNum);
                        readInfo.setReadNum(initNum - readInfo.getInitNum());
                        readInfo.setState(1);
                    }
                } else {
                    readInfo.setState(3);
                }
                readInfoMapper.updateReadInfo(readInfo);
                System.out.println(formater.format(new Date()) + "   ip:" + serverConfig.getUrl() + "  发现可执行链接:" + readInfo.getUrl() + ",id:" + readInfo.getId());
                //获取微信号并导入redis
                List<ReadWx> readWxList = readWxMapper.selectReadWxList(new ReadWx());
                redisCache.deleteObject(RedisKeys.getWxUserList(readInfo.getUrl()));
                for (ReadWx readWx : readWxList) {
                    //10分钟内已阅读过的，不再进行阅读
                    Object readWxUrl = redisCache.getCacheObject(RedisKeys.getUserReadWx(readInfo.getUrl(), readWx.getWxId()));
                    if (readWxUrl == null) {
                        redisCache.leftPushList(RedisKeys.getWxUserList(readInfo.getUrl()), JSON.toJSONString(readWx));
                    }
                }
                fixedThreadPool.execute(new Runnable() {
                    @Override
                    public void run() {
                        if (readInfo.getState() == 1 && readInfo.getEndNum() > 0) {
                            //阅读
                            dealRead(readInfo);
                        }
                    }
                });
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 阅读链接
     *
     * @param readInfo
     */
    public void dealRead(ReadInfo readInfo) {
        long time1 = System.currentTimeMillis();
        //获取链接
        String url = readInfo.getUrl();
        List<Future<Boolean>> futureList = new ArrayList<>();
        //判断订单是否存在，存在中途删除订单的可能性
        readInfo = readInfoMapper.selectReadInfoById(readInfo.getId());
        if (readInfo != null) {
            //判断是否有足够的微信号，如果没有就退出
            long readWxSize = redisCache.getListSize(RedisKeys.getWxUserList(url));
            if (readWxSize == 0) {
                readInfo.setState(3);
                readInfoMapper.updateReadInfo(readInfo);
                return;
            }
            int userWxSize = readInfo.getNeedNum();
            if (readInfo.getEndNum() > 0) {
                //进行阅读
                for (int i = 0; i < readInfo.getNeedNum(); i++) {
                    try {
                        Future future = executorService.submit(new Callable<Object>() {
                            @Override
                            public Object call() throws Exception {
                                //查询出可用的微信号
                                Object readObj = redisCache.rightPopList(RedisKeys.getWxUserList(url));
                                if (readObj != null) {
                                    ReadWx readWx = JSON.parseObject(readObj.toString(), ReadWx.class);
                                    //阅读文章
                                    WxGetA8KeyTo wxGetA8KeyTo = new WxGetA8KeyTo();
                                    wxGetA8KeyTo.setKey(readWx.getWxId());
                                    wxGetA8KeyTo.setNode(readWx.getServer());
                                    wxGetA8KeyTo.setUrl(url);
                                    WxGetA8KeyBean wxGetA8KeyBean = wxApiServer.wxGetA8Key(wxGetA8KeyTo);
                                    if (wxGetA8KeyBean.isSuccess()) {
                                        Map<String, String> headerMap = new HashMap<>();
                                        headerMap.put("X-WECHAT-KEY", wxGetA8KeyBean.getWeChatKey());
                                        headerMap.put("X-WECHAT-UIN", wxGetA8KeyBean.getWeChatUin());
                                        headerMap.put("exportkey", wxGetA8KeyBean.getExportKey());
                                        headerMap.put("Cookie", wxGetA8KeyBean.getCookie());
                                        String ret = OkHttpUtils.httpGet(wxGetA8KeyBean.getFullUrl(), headerMap);
                                        if (StringUtils.isNotBlank(ret)) {
                                            //阅读成功，说明该号已读过，10分钟内不再用改号阅读
                                            redisCache.setCacheObject(RedisKeys.getUserReadWx(url, readWx.getWxId()), 1, 10, TimeUnit.MINUTES);
                                            return true;
                                        }
                                    }
                                }
                                return false;
                            }
                        });
                        futureList.add(future);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                //等待完成阅读
                for (int i = 0; i < futureList.size(); i++) {
                    try {
                        boolean ret = futureList.get(i).get();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                //获取最新的值
                ReadInit readInit = getReadNum(readInfo.getUrl());
                int nowNum = readInit.getInitNum();
                //获取状态是0
                if (readInit.isReadStatus() == false || nowNum < readInfo.getInitNum()) {
                    readInfo.setState(3);
                    readInfoMapper.updateReadInfo(readInfo);
                    return;
                } else {
                    //本轮阅读值
                    int thisNum = nowNum - readInfo.getNowNum();
                    //获取已阅读的值
                    int readNum = nowNum - readInfo.getInitNum();
                    //未阅读量
                    int needNum = readInfo.getEndNum() - nowNum;
                    readInfo.setReadNum(readNum);
                    readInfo.setNowNum(nowNum);
                    readInfo.setNeedNum(needNum);
                    readInfoMapper.updateReadInfo(readInfo);
                    long time2 = System.currentTimeMillis();
                    long time = time2 - time1;
                    System.out.println("-------------------------"
                            + "\nid:" + readInfo.getId()
                            + "\n耗时:" + time
                            + "\n线程:" + Thread.currentThread().getName()
                            + "\nip:" + serverConfig.getUrl()
                            + "\n剩余链接数:" + readWxSize
                            + "\n本轮使用链接数:" + userWxSize
                            + "\n本轮阅读值:" + thisNum
                            + "\n链接初始值:" + readInfo.getInitNum()
                            + "\n链接当前值:" + nowNum
                            + "\n链接结束值:" + readInfo.getEndNum()
                            + "\n当前总阅读值:" + readNum
                            + "\n下轮需要阅读数:" + needNum + "\n----------------------------------------");
                    //通过判断最终值和当前阅读值判断，是否已满足
                    if (needNum > 0) {
                        dealRead(readInfo);
                    } else {
                        readInfo.setState(2);
                        readInfo.setNeedNum(0);
                        readInfo.setComTime(new Date());
                        readInfoMapper.updateReadInfo(readInfo);
                        return;
                    }
                }
            }
        }
    }

    /**
     * 处理未完成的任务
     */
    public void dealUnFinish() {
        List<ReadInfo> readInfoList = new ArrayList<>();
        ReadInfo readSearchInfo = new ReadInfo();
        readSearchInfo.setState(3);
        List<ReadInfo> readInfoList3 = readInfoMapper.selectReadInfoList(readSearchInfo);
        readSearchInfo.setState(2);
        List<ReadInfo> readInfoList2 = readInfoMapper.selectReadInfoList(readSearchInfo);
        readInfoList.addAll(readInfoList2);
        readInfoList.addAll(readInfoList3);
        for (ReadInfo readInfo : readInfoList) {
            if (readInfo.getNeedNum() > 0) {
                readInfo.setState(0);
                readInfoMapper.updateReadInfo(readInfo);
            }
        }
    }

    /**
     * 加载在线微信
     */
    public void dealReadWx() {
        while (true) {
            try {
                List<ReadWx> newWxList = new ArrayList<>();
                List<ReadWx> nowWxList = readWxMapper.selectAllReadWx();
                List<ReadUser> readUserList = readUserMapper.selectReadUser(new ReadUser());
                //获取所有的微信
                for (ReadUser readUser : readUserList) {
                    String ret = OkHttpUtils.httpGet(readUser.getUser());
                    JSONObject jsonObject = JSON.parseObject(ret);
                    JSONArray dataList = jsonObject.getJSONArray("data");
                    if (dataList != null && dataList.size() != 0) {
                        for (Object dataObj : dataList) {
                            JSONObject obj = JSON.parseObject(dataObj.toString());
                            int type = Integer.parseInt(readUser.getPwd());
                            String server = obj.getString("server");
                            String wxId = obj.getString("wxId");
                            ReadWx readWx = new ReadWx();
                            readWx.setType(type);
                            readWx.setReadNum(0);
                            readWx.setReadStatus(0);
                            readWx.setAllNum(0);
                            readWx.setServer(server);
                            readWx.setWxId(wxId);
                            newWxList.add(readWx);
                        }
                    }
                }
                if (newWxList.size() != 0) {
                    //查询所有的新增数据
                    List newAllWxList = newWxList.stream().filter(item -> !nowWxList.stream().map(e -> e.getWxId()).collect(Collectors.toList()).contains(item.getWxId())).collect(Collectors.toList());
                    List delWxList = nowWxList.stream().filter(item -> !newWxList.stream().map(e -> e.getWxId()).collect(Collectors.toList()).contains(item.getWxId())).collect(Collectors.toList());
                    //删除
                    Long delIds[] = new Long[delWxList.size()];
                    for (int i = 0; i < delWxList.size(); i++) {
                        ReadWx readWx = (ReadWx) delWxList.get(i);
                        delIds[i] = readWx.getId();
                    }
                    if (delIds.length != 0) readWxMapper.deleteReadWxByIds(delIds);
                    //新增
                    if (newAllWxList.size() != 0) readWxMapper.batchInsertWx(newAllWxList);
                    System.out.println(formater.format(new Date()) + " " + "新增:" + newAllWxList.size() + "  删除:" + delIds.length + "  当前:");
                    //查询所有正在跑的链接
                    ReadInfo readInfo = new ReadInfo();
                    readInfo.setState(1);
                    List<ReadInfo> readInfoList = readInfoMapper.selectReadInfoList(readInfo);
                    //将新增的账号插入到对应的微信号列表
                    for (ReadInfo info : readInfoList) {
                        for (int i = 0; i < newAllWxList.size(); i++) {
                            ReadWx readWx = (ReadWx) newAllWxList.get(i);
                            redisCache.rightPushList(RedisKeys.getWxUserList(info.getUrl()), JSON.toJSONString(readWx));
                        }
                    }
                }
                Thread.sleep(10 * 1000);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 链接处理类，每天4点清理数据
     */
    public void delInfo() {
        while (true) {
            try {
                Calendar now = Calendar.getInstance();
                int minute = now.get(Calendar.MINUTE);
                int hour = now.get(Calendar.HOUR_OF_DAY);
                System.out.println(hour + "：" + minute);
                if (hour == 4 && minute == 0) {
                    List<ReadInfo> readInfoList = new ArrayList<>();
                    ReadInfo readSearchInfo = new ReadInfo();
                    readSearchInfo.setState(2);
                    readInfoList = readInfoMapper.selectReadInfoList(readSearchInfo);
                    for (ReadInfo readInfo : readInfoList) {
                        redisCache.deleteObject(RedisKeys.orderStatus(readInfo.getUrl()));
                    }
                    readInfoMapper.deleteAll();
                }
                Thread.sleep(1000 * 60);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /////////////工具类//////////////////////////////

    /**
     * 检测链接有效性
     *
     * @param url
     * @return
     */
    public static boolean checkUrl(String url) {
        url = url.trim();
        boolean retBool = isURL(url);
        if (retBool) {
            String ret = OkHttpUtils.httpGet(url);
            if (StringUtils.isNotBlank(ret) && ret.contains("微信公众平台")) {
                return true;
            }
        }
        return false;
    }

    /**
     * 检测是否是链接
     *
     * @param str
     * @return
     */
    public static boolean isURL(String str) {
        //转换为小写
        str = str.toLowerCase();
        String regex = "^((https|http|ftp|rtsp|mms)?://)"  //https、http、ftp、rtsp、mms
                + "?(([0-9a-z_!~*'().&=+$%-]+: )?[0-9a-z_!~*'().&=+$%-]+@)?" //ftp的user@
                + "(([0-9]{1,3}\\.){3}[0-9]{1,3}" // IP形式的URL- 例如：199.194.52.184
                + "|" // 允许IP和DOMAIN（域名）
                + "([0-9a-z_!~*'()-]+\\.)*" // 域名- www.
                + "([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\\." // 二级域名
                + "[a-z]{2,6})" // first level domain- .com or .museum
                + "(:[0-9]{1,5})?" // 端口号最大为65535,5位数
                + "((/?)|" // a slash isn't required if there is no file name
                + "(/[0-9a-z_!~*'().;?:@&=+$,%#-]+)+/?)$";
        return str.matches(regex);
    }

    /**
     * 检测是否是纯数字
     *
     * @param str
     * @return
     */
    public static boolean isNumeric(String str) {
        for (int i = 0; i < str.length(); i++) {
            if (!Character.isDigit(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    /**
     * 获取初始值
     *
     * @param url
     * @return
     */
    public ReadInit getReadNum(String url) {
        int readNum = 0;
        ReadInit readInit = new ReadInit();
        ReadWx readSearchWx = new ReadWx();
        List<ReadWx> readWxList = readWxMapper.selectReadWxList(readSearchWx);
        Collections.reverse(readWxList);
        for (ReadWx readWx : readWxList) {
            Object readWxObj = redisCache.getCacheObject(RedisKeys.readNumStatus(readWx.getWxId()));
            if (null == readWxObj) {
                redisCache.setCacheObject(RedisKeys.readNumStatus(readWx.getWxId()), 1, 5, TimeUnit.SECONDS);
                WxReadBizArticleTo wxReadBizArticleTo = new WxReadBizArticleTo();
                wxReadBizArticleTo.setUrl(url);
                wxReadBizArticleTo.setKey(readWx.getWxId());
                wxReadBizArticleTo.setNode(readWx.getServer());
                WxReadBean wxReadBean = wxApiServer.wxReadArticle(wxReadBizArticleTo);
                if (wxReadBean.isSuccess()) {
                    readNum = wxReadBean.getReadNum();
                    readInit.setInitNum(readNum);
                    readInit.setReadStatus(true);
                    break;
                }
            }
        }
        return readInit;
    }
}
